package com.symaster.backups.frame.page.viewfiles;

import com.symaster.backups.enumerate.FileSystemStatus;
import com.symaster.backups.frame.MainFrame;
import com.symaster.backups.frame.dialog.AddMonitorFolderDialog;
import com.symaster.backups.frame.dialog.RollbackDialog;
import com.symaster.backups.frame.element.collapsev2.CollapseItem;
import com.symaster.backups.frame.element.layout.TileLayout;
import com.symaster.backups.frame.element.scrollbar.Scrollbar;
import com.symaster.backups.manager.EventManager;
import com.symaster.backups.manager.EventRunnable;
import com.symaster.backups.manager.TaskManager;
import com.symaster.backups.model.FileSystemMonitorModel;
import com.symaster.backups.repository.FileSystemMonitorRepository;
import com.symaster.backups.repository.data2.FileSystemMonitorBackupData2;
import com.symaster.common.swing.util.SwingUtil;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.List;

import static com.symaster.backups.util.ComponentUtil.separatorPanel;

/**
 * @author yinmiao
 * @version 2024/2/5
 */
@Getter
@Component
public class FileBackupView extends MainFrame.Item {

    private final FileSystemMonitorRepository fileSystemMonitorRepository;
    private final FileSystemMonitorBackupData2 fileSystemMonitorBackupData2;
    private final FileBackupToolbar fileBackupToolbar;
    private final FileBackupList fileBackupList;
    private final Scrollbar scrollbar;
    private final AddMonitorFolderDialog addMonitorFolderDialog;
    private final EventManager eventManager;
    private final RollbackDialog rollbackDialog;
    private final TaskManager taskManager;

    @Autowired
    public FileBackupView(FileSystemMonitorRepository fileSystemMonitorRepository, FileSystemMonitorBackupData2 fileSystemMonitorBackupData2,
                          AddMonitorFolderDialog addMonitorFolderDialog,
                          EventManager eventManager,
                          RollbackDialog rollbackDialog, TaskManager taskManager) {
        this.fileSystemMonitorRepository = fileSystemMonitorRepository;
        this.fileSystemMonitorBackupData2 = fileSystemMonitorBackupData2;
        this.addMonitorFolderDialog = addMonitorFolderDialog;
        this.eventManager = eventManager;
        this.rollbackDialog = rollbackDialog;
        this.taskManager = taskManager;

        /* 注册一个事件 */
        eventManager.register("RELOAD_BACKUP_VIEW", new EventRunnable() {
            @Override
            public void trigger(Object param) {
                viewEvent();
            }

            @Override
            public boolean mainFrameVisible() {
                return true;
            }
        });

        setLayout(new BorderLayout());
        add((fileBackupToolbar = getFileBackupToolbar()), BorderLayout.WEST);

        JPanel jPanel = new JPanel();
        jPanel.setLayout(new BorderLayout());
        jPanel.add(separatorPanel(), BorderLayout.WEST);
        jPanel.add(scrollbar = new Scrollbar(), BorderLayout.CENTER);
        scrollbar.setContentPane(fileBackupList = getFileBackupList());
        add(jPanel, BorderLayout.CENTER);
    }

    private FileBackupToolbar getFileBackupToolbar() {
        FileBackupToolbar fileBackupToolbar = new FileBackupToolbar(this, addMonitorFolderDialog);
        fileBackupToolbar.setPreferredSize(new Dimension(200, 1));
        fileBackupToolbar.setBorder(new EmptyBorder(10, 10, 10, 10));
        return fileBackupToolbar;
    }

    private static FileBackupList getFileBackupList() {
        FileBackupList fileBackupList = new FileBackupList();
        fileBackupList.setLayout(new TileLayout(3));
        fileBackupList.setBorder(new EmptyBorder(10, 5, 10, 5));
        return fileBackupList;
    }

    @Override
    public String label() {
        return "自动备份";
    }

    @Override
    public void viewEvent() {
        eventManager.removeAllByKey("MONITOR_UPDATE");
        List<Item> all = fileSystemMonitorRepository.views()
                .stream()
                .map(e -> new Item(e, this, eventManager, rollbackDialog))
                .toList();

        fileBackupList.removeAll();
        all.forEach(fileBackupList::add);
        fileBackupList.validate();
        scrollbar.validate();
    }

    public static class Item extends CollapseItem implements Serializable {
        private FileSystemMonitorModel fileSystemMonitorModel;

        private JLabel statusLabel;
        private final Font font1;
        private final JPanel top;

        private final FileBackupView fileBackupView;
        private final RollbackDialog rollbackDialog;
        private static final EmptyBorder labelEmptyBorder = new EmptyBorder(0, 5, 0, 5);
        private static final int labelWidth = 160;
        private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        private final JLabel pathName = new JLabel();
        private final JLabel fileCount = new JLabel();
        private final JLabel folderCount = new JLabel();
        private final JLabel lastScan = new JLabel();
        private final JLabel lastBackup = new JLabel();

        public Item(FileSystemMonitorModel fileSystemMonitorModel,
                    FileBackupView fileBackupView,
                    EventManager eventManager,
                    RollbackDialog rollbackDialog) {
            this.fileSystemMonitorModel = fileSystemMonitorModel;
            this.rollbackDialog = rollbackDialog;
            this.fileBackupView = fileBackupView;

            eventManager.register("MONITOR_UPDATE", new EventRunnable() {
                @Override
                public void trigger(Object param) {
                    if (param instanceof FileSystemMonitorModel monitor) {
                        if (fileSystemMonitorModel.getId().equals(monitor.getId())) {
                            Item.this.fileSystemMonitorModel = monitor;
                            dataUpdate();
                        }
                    }
                }

                @Override
                public boolean mainFrameVisible() {
                    return true;
                }
            });

            top = new JPanel();
            top.setBorder(new EmptyBorder(5, 10, 5, 10));
            top.setLayout(new BorderLayout());
            top.setOpaque(false);

            JLabel jLabel = new JLabel(new File(fileSystemMonitorModel.getPathName()).getName());

            Font font = jLabel.getFont();
            font1 = new Font(font.getFontName(), font.getStyle(), font.getSize() - 1);
            Font font2 = new Font(font.getFontName(), Font.BOLD, font.getSize() + 1);

            jLabel.setFont(font2);
            jLabel.setBorder(labelEmptyBorder);
            top.add(jLabel, BorderLayout.CENTER);

            JPanel centerPanel = centerPanel();
            centerPanel.add(viewItem_row1());
            centerPanel.add(viewItem_row2());
            centerPanel.add(viewItem_row3());
            centerPanel.add(viewItem_row4());
            dataUpdate();

            JToolBar jToolBar = getjToolBar();

            JPanel jPanel1 = new JPanel();
            jPanel1.setOpaque(false);
            jPanel1.setVisible(false);
            jPanel1.setLayout(new BorderLayout());
            jPanel1.add(centerPanel, BorderLayout.CENTER);
            jPanel1.add(jToolBar, BorderLayout.SOUTH);

            setTop(top);
            setCenter(jPanel1);

            addRefreshListener(() -> Item.this.refresh(Item.this.getParent().getParent()));
        }

        private JToolBar getjToolBar() {
            JButton jButton = new JButton(fileSystemMonitorModel.getMonitor() ? "暂停备份" : "继续备份");
            jButton.addActionListener(e -> {
                if (e.getSource() instanceof JButton button) {

                    if (fileSystemMonitorModel.getMonitor()) {
                        fileBackupView.fileSystemMonitorBackupData2.updateMonitor(fileSystemMonitorModel.getId(), false);
                        button.setText("继续备份");
                    } else {
                        fileBackupView.fileSystemMonitorBackupData2.updateMonitor(fileSystemMonitorModel.getId(), true);
                        button.setText("暂停备份");
                    }

                    fileSystemMonitorModel = fileBackupView.fileSystemMonitorRepository
                            .findById(fileSystemMonitorModel.getId())
                            .orElseThrow(NullPointerException::new);
                    dataUpdate();
                }
            });

            JToolBar jToolBar = new JToolBar();
            jToolBar.setLayout(new FlowLayout(FlowLayout.RIGHT, 15, 0));
            jToolBar.add(jButton);
            return jToolBar;
        }

        private void refresh(Container container) {
            container.doLayout();
            container.repaint();

            for (java.awt.Component component : container.getComponents()) {
                if (component instanceof Container c) {
                    refresh(c);
                }
            }
        }

        private void dataUpdate() {
            setupPathName();
            setupFileCount();
            setupFolderCount();
            setupLastScan();
            setupLastBackup();
            setupStatus();
        }

        private static JPanel centerPanel() {
            JPanel jPanel1 = new JPanel();
            jPanel1.setOpaque(false);
            jPanel1.setBorder(new EmptyBorder(10, 5, 0, 10));
            jPanel1.setLayout(new TileLayout(0));
            return jPanel1;
        }

        private JComponent viewItem_row1() {
            JComponent ret = new JToolBar();
            ret.setOpaque(false);
            ret.setLayout(new FlowLayout(FlowLayout.LEADING, 10, 0));

            ret.add(new JLabel("本地路径:"));
            ret.add(pathName);

            JButton jButton = new JButton("打开目录", SwingUtil.loadIcon("folder.png", 13, 13));
            jButton.addActionListener(e -> {
                try {
                    SwingUtil.openFolder(new File(fileSystemMonitorModel.getPathName()));
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            });
            ret.add(jButton);
            return ret;
        }

        private JComponent viewItem_row2() {
            JComponent ret = new JToolBar();
            ret.setOpaque(false);
            ret.setLayout(new FlowLayout(FlowLayout.LEADING, 10, 0));

            JLabel jLabel1 = new JLabel("数量:");
            ret.add(jLabel1);
            ret.add(fileCount);
            ret.add(folderCount);

            return ret;
        }

        private JComponent viewItem_row3() {
            JComponent ret = new JToolBar();
            ret.setOpaque(false);
            ret.setLayout(new FlowLayout(FlowLayout.LEADING, 10, 0));

            ret.add(new JLabel("最后备份:"));

            ret.add(lastBackup);

            JButton jButton = new JButton("恢复文件", SwingUtil.loadIcon("rollback.png", 12, 12));
            jButton.addActionListener(e -> {
                rollbackDialog.setTitle("恢复文件");
                Point locationOnScreen = jButton.getLocationOnScreen();
                rollbackDialog.setBounds(locationOnScreen.x - 200, locationOnScreen.y - 10, 600, 400);
                rollbackDialog.open(fileSystemMonitorModel);
            });
            ret.add(jButton);

            return ret;
        }

        private JComponent viewItem_row4() {
            JComponent ret = new JToolBar();
            ret.setOpaque(false);
            ret.setLayout(new FlowLayout(FlowLayout.LEADING, 10, 0));

            ret.add(new JLabel("最后扫描:"));
            ret.add(lastScan);
            return ret;
        }

        private void setupLastBackup() {
            lastBackup.setText(fileSystemMonitorModel.getLastBackup());
        }

        private void setupLastScan() {
            lastScan.setText(fileSystemMonitorModel.getLastScan() != null ? SDF.format(fileSystemMonitorModel.getLastScan()) : "NUL");
        }

        private void setupPathName() {
            pathName.setText(fileSystemMonitorModel.getPathName());
        }

        private void setupFolderCount() {
            folderCount.setText(String.format("%s文件夹", fileSystemMonitorModel.getFolderCount() == null ? 0 : fileSystemMonitorModel.getFolderCount()));
        }

        private void setupFileCount() {
            fileCount.setText(String.format("%s文件", fileSystemMonitorModel.getFileCount() == null ? 0 : fileSystemMonitorModel.getFileCount()));
        }

        private void setupStatus() {
            if (statusLabel == null) {
                statusLabel = new JLabel();
                statusLabel.setBorder(labelEmptyBorder);
                statusLabel.setFont(font1);
                top.add(statusLabel, BorderLayout.EAST);
            }

            if (fileSystemMonitorModel.getMonitor()) {
                FileSystemStatus fileSystemStatus = FileSystemStatus.ofCode(fileSystemMonitorModel.getStatus());
                statusLabel.setText(fileSystemStatus.getLabel());
                statusLabel.setForeground(fileSystemStatus.getColor());
            } else {
                statusLabel.setText("备份暂停");
                statusLabel.setForeground(new Color(0, 0, 0));
            }
        }
    }
}
